#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

int main()
{
  pid_t id=fork();
  assert(id!=-1);
  if(id==0)
  {
    //通过创建子进程的方式调用exec*，然后父进程进行等待    
    sleep(1);

    // l表示可变参数由列表构成
    // execl("/usr/bin/ls,"ls","-a","-l","--color=auto",NULL);

    // p代表PATH，带'p'的函数，不用告诉函数程序的路径，只需写明是谁，函数会自动在环境变量PATH中查找可执行程序
    // execlp("ls","ls","-a","-l","--color=auto",NULL);

    char* const _argv[]={
      (char*)"ls",
      (char*)"-a",
      (char*)"-l",
      (char*)"--color=auto",
      NULL
    };

    // v代表vector，可以将所有执行参数放入指针数组中统一传参
    // execv("/usr/bin/ls",_argv);

    // v，p综合上面两种情况
    // execvp("ls",_argv);

    // exec*系列的函数除了可以执行系统的程序，还可以执行我自己写的程序
    // execlp("./mybin","mybin",NULL);

    // 除此之外，还可以调用任何其他后端语言
    // execlp("./mycpp","./mycpp",NULL);
    // execlp("./mypython.py","mypython.py",NULL);
    // execlp("./myshell.sh","myshell.sh",NULL);

    // 与环境变量相关的接口
    // execle("./mybin","mybin",NULL);    // 不传环境变量的话会调用失败->perror会显示：“Bad address”

    char*const _env[]={
      (char*)"PWD",
      (char*)"MY_ENV=123456789",
      NULL
    };

    // 如果我们自定义_env这个参数，系统那一套就不会被execle拿到了
    // 即使像PWD这样的环境变量也没有被execle拿到
    // execle("./mybin","mybin",NULL,_env);   // 自定义环境变量

    extern char** environ;                    

    char MY_ENV[]="MY_ENV=12345678";
    putenv(MY_ENV);   // 将指定的环境变量导入environ所指向的char*数组中

    execle("./mybin","mybin",NULL,environ);   // 系统环境变量，实际上，默认系统环境变量你不传，子进程也能获取(也通过environ这个二级指针)



    perror("exec");
    exit(66);     // 退出码设为66
  }

  // 父进程
  int status = 0;
  pid_t ret=waitpid(id,&status,0);    // 阻塞时等待
  if(ret>0)
  {
    printf("wait success!,sig_num: %d,exit_code:%d\n",status&0x7F,(status>>8)&0xFF);
  }

  //初步演示exec函数，见见猪跑
  //printf("process is running...\n");

  //execl("/usr/bin/ls","ls","-a","-l","--color=auto",NULL);

  // execl调用成功，不需要返回，因为发生进程替换，返回无意义
  //printf("process done!\n");
  return 0;
}
